#include "stdafx.h"
#include "Demo.h"

#include "Engine.h"
#include "Timer.h"

Demo::Demo(SoundPtr soundtrack)
: soundtrack(soundtrack), last_gather(-1.0f), time(0.0f), start_time(0.0f)
{
}

Demo::~Demo()
{
	for(uint i = 0; i < segments.size(); ++i)
		segments[i].segment->close();
	segments.clear();
}

void Demo::add(int priority, float start, float end, TimelineSegmentPtr segment)
{
	assert(start < end);

	DemoSegment new_segment;
	new_segment.priority = priority;
	new_segment.start = start;
	new_segment.end = end;
	new_segment.segment = segment;
	segments.push_back(new_segment);

	segment->init(shared_from_this());
}

void Demo::seal()
{
	std::sort(segments.begin(), segments.end());
}

float Demo::getTime()
{
	return time;
}

void Demo::setTime(float t)
{
	soundtrack->setPosition(t);
	time = t;
}

float Demo::getCurrentSegmentLength()
{
	return current_segment_length;
}

void Demo::pause()
{
	soundtrack->pause();
}

void Demo::play()
{
	soundtrack->play();
}

bool Demo::update()
{
	time = soundtrack->getPosition();

	Engine e;

	if(segments.size() > 0)
	{
		DemoSegment& last = segments[segments.size()-1];
		if(time >= soundtrack->getLength()	|| e.getInput()->getKeyboard()->isKeyPressed(VK_ESCAPE))
		{
			for(uint i = 0; i < segments.size(); ++i)
				segments[i].segment->close();
			segments.clear();
			return false;
		}
	}
	else
		return false;

	DemoSegment active_segments[max_active_segments];
	uint active_segment_count = gatherActiveSegments(time, active_segments);

	for(uint i = 0; i < active_segment_count; ++i)
	{
		DemoSegment& s = active_segments[i];
		current_segment_length = s.end - s.start;
		s.segment->update(time);
	}
	return true;
}

bool Demo::render()
{
	DemoSegment active_segments[max_active_segments];
	uint active_segment_count = gatherActiveSegments(time, active_segments);

	for(uint i = 0; i < active_segment_count; ++i)
	{
		DemoSegment& s = active_segments[i];
		current_segment_length = s.end - s.start;
		s.segment->render(time);
	}
	return true;
}

bool Demo::comparePriorities(const DemoSegment& s1, const DemoSegment& s2) 
{
	return s1.priority < s2.priority;
}

uint Demo::gatherActiveSegments(float t, DemoSegment out[])
{
	uint count = 0;
	for(uint i = 0; i < segments.size(); ++i)
	{
		if(segments[i].start <= t && segments[i].end >= t)
			out[count++] = segments[i];
		if(count >= max_active_segments)
			throw EXCEPTION("Active timeline segment buffer owerflow");
	}
	std::sort(out, out + count, comparePriorities);
	return count;
}


